"""
程序分析模块 - 分析目标程序的特征
"""

import os
import subprocess


class ProgramAnalyzer:
    def analyze_program(self, program_path):
        """分析程序特征"""
        analysis = {
            'file_type': '',
            'dangerous_functions': [],
            'input_methods': [],
            'file_size': 0,
            'strings': [],
            'has_source': False,
            'program_type': 'binary'  # 默认类型
        }

        if os.path.exists(program_path):
            # 文件类型
            analysis['file_type'] = self._get_file_type(program_path)

            # 文件大小
            analysis['file_size'] = os.path.getsize(program_path)

            # 检查是否为源代码
            if program_path.endswith('.c'):
                analysis['has_source'] = True
                analysis['program_type'] = 'c'
                content = self._read_file_content(program_path)
                analysis['dangerous_functions'] = self._find_dangerous_functions(content)
                analysis['input_methods'] = self._find_input_methods(content)
            elif program_path.endswith(('.cpp', '.cc', '.cxx')):
                analysis['has_source'] = True
                analysis['program_type'] = 'cpp'
                content = self._read_file_content(program_path)
                analysis['dangerous_functions'] = self._find_dangerous_functions(content)
                analysis['input_methods'] = self._find_input_methods(content)
            else:
                # 二进制文件分析
                analysis['has_source'] = False
                analysis['strings'] = self._extract_strings(program_path)

        return analysis

    def _get_file_type(self, file_path):
        """获取文件类型"""
        try:
            result = subprocess.run(['file', file_path], capture_output=True, text=True)
            return result.stdout.strip()
        except:
            return 'Unknown'

    def _read_file_content(self, file_path):
        """读取文件内容"""
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                return f.read()
        except Exception as e:
            print(f" 读取文件失败 {file_path}: {e}")
            return ""

    def _extract_strings(self, file_path):
        """提取二进制文件中的字符串"""
        try:
            result = subprocess.run(['strings', file_path], capture_output=True, text=True)
            return [s for s in result.stdout.split('\n') if s.strip()][:50]
        except:
            return []

    def _find_dangerous_functions(self, code):
        """在代码中查找危险函数"""
        dangerous_patterns = [
            'strcpy', 'strcat', 'gets', 'sprintf', 'vsprintf',
            'scanf', 'printf', 'system', 'exec', 'malloc', 'free',
            'memcpy', 'strncpy', 'vsprintf', 'vprintf'
        ]
        found = []
        for pattern in dangerous_patterns:
            if pattern in code:
                found.append(pattern)
        return list(set(found))

    def _find_input_methods(self, code):
        """查找输入处理方法"""
        input_methods = []
        patterns = {
            'stdin_input': ['fgets', 'gets', 'getchar', 'fgetc'],
            'formatted_input': ['scanf', 'fscanf', 'sscanf'],
            'command_line_args': ['argc', 'argv'],
            'binary_input': ['fread', 'read', 'recv'],
            'file_input': ['fopen', 'open', 'freopen']
        }

        for method, funcs in patterns.items():
            for func in funcs:
                if func in code:
                    input_methods.append(method)
                    break

        return list(set(input_methods))